﻿#ifndef QTTAUDIO_QTTCHANNEL_H
#define QTTAUDIO_QTTCHANNEL_H

#include <cstdint>
#if defined(_WIN32) || defined(__CYGWIN__)
#define QTT_PUBLIC_CALLBACK __stdcall
#define QTT_PUBLIC __declspec(dllexport)
#else
#define QTT_PUBLIC __attribute__((visibility("default")))
#if !defined(ANDROID) && !defined(APPLE)
#define LINUX_DEVICE
#include "QttSoundCard.h"
#endif
#endif

/**
 * 频道高级API
 */
namespace Qtt {
/**
 * 频道用户角色：主播和听众
 */
enum ChannelRole {
	TALKER = 0,  //主播，可说可听
	AUDIENCE = 1 //听众，只能听不能说
};
/**
 * 频道用户
 */
class ChannelUser {
public:
	uint32_t uid; //用户id
	bool muted;  //是否mute
	ChannelRole audioRole; //用户角色
	int jitter; //抖动
	int curbps; //Bps，字节没秒
	int lossRate; //丢包率，百分数0-100
	int distance; //user->me的端到端时延毫秒
	int volume; //音量，默认为100，范围在[0-400]
	void *extra; //用户设置，方便存一个变量

	bool enableVideo;
	int witdh;
	int height;

	ChannelUser(uint32_t uid, bool muted, ChannelRole role) {
		ChannelUser::uid = uid;
		ChannelUser::muted = muted;
		ChannelUser::audioRole = role;
		extra = NULL;
		jitter = 0;
		curbps = 0;
		lossRate = 0;
		distance = 0;
		volume = 100;
		enableVideo = false;
	}
	virtual ~ChannelUser() {
	}
};

/**
 * 频道观察者
 */
class ChannelObserver {
public:
	/**
	 * 自己加入成功，实现加入房间成功的逻辑
	 * @param role 加入角色
	 */
	virtual void onJoinSuccess(uint32_t roomId, uint32_t uid, ChannelRole role) = 0;
	/**
	 * 自己加入失败，实现加入房间失败的逻辑
	 * @param code 失败状态
	 * @param message 失败信息
	 */
	virtual void onJoinFail(int code, const char *message) = 0;
	/**
	 * 断线重连时，会回调该函数进行通知
	 * @param seconds 在多少秒后进行重连
	 * @return true为继续等待重连，false为取消重连
	 */
	virtual bool onWaitReconnecting(int seconds) = 0;
	/**
	 * 链接断开，实现退出房间的逻辑
	 */
	virtual void onClose() = 0;
	/**
	 * 自己说话状态，实现自己说话音量状态改变的逻辑
	 * @param talking [0-600), 0没说话
	 */
	virtual void onSelfTalking(int talking) = 0;
	/**
	 * 其他用户加入，实现别人进入房间的逻辑
	 * @param user
	 */
	virtual void onOtherJoin(ChannelUser *user) = 0;
	/**
	 * 其他用户说话状态，实现他人说话音量状态改变的逻辑
	 * @param user
	 * @param talking talking [0-600), 0没说话
	 */
	virtual void onOtherTalking(ChannelUser *user, int talking) = 0;
	/**
	 * 其他用户mute状态，实现别人静音状态改变的逻辑
	 * @param user
	 */
	virtual void onOtherMuted(ChannelUser *user) = 0;
	/**
	 * 自己角色改变，实现自己连麦角色状态改变的逻辑
	 * @param role
	 */
	virtual void onSelfRoleChanged(ChannelRole role) = 0;
	/**
	 * 其他用户角色改变，实现别人连麦角色状态改变的逻辑
	 * @param user
	 */
	virtual void onOtherRoleChanged(ChannelUser *user) = 0;
	/**
	 * 用户网络统计，实现他人网络情况统计的逻辑
	 * @param user
	 */
	virtual void onOtherNetworkStats(ChannelUser *user) = 0;
	/**
	 * 用户网络统计，实现自己网络情况统计的逻辑
	 * @param user
	 * @param myRtt 自己与server端的RTT
	 */
	virtual void onSelfNetworkStats(int myRtt) = 0;
	/**
	 * 其他用户离开，实现别人离开房间的逻辑
	 * @param user
	 */
	virtual void onOtherLeave(ChannelUser *user) = 0;

	virtual ~ChannelObserver() {};
};

/**
 * 声音数据观察者
*/
class AudioDataObserver {
public:
	/**
	 * 获取到数据
	 * @param buf
	 * @param len
	 * @param observerId
	 */
	virtual void onRecordData(char *buf, const int len) = 0;
	virtual void onPlaybackData(char *buf, const int len) = 0;
	virtual ~AudioDataObserver() {};
};
/**
 * 播放器，适合播放任何文件形式的数据内容
 */
class ChannelPlayer {
public:
	/**
	 * 写入pcm数据播放
	 * @param buf
	 * @param len
	 * @return 0成功,其他失败
	 */
	virtual int write(char *buf, int len) = 0;
	/**
	 * 调节写入的音量
	 * @param vol, [0-400],默认是100
	 */
	virtual void adjustVolume(int vol) = 0;

	virtual ~ChannelPlayer() {};
};
/**
 * 将通话抽象为进入房间,同一个房间内的用户可互相语聊
 */
class ChannelEngine {
public:
#ifdef LINUX_DEVICE
	////BEGIN 针对嵌入式Linux设备使用调参 BEGIN//////
	/**
	 * 针对嵌入式linux,用户可以继承SoundCard类实现声音的采集和播放模型
	 * @param recorder 声音采集对象
	 * @param player 声音播放对象
	 */
	virtual void useCustomeSoundCard(SoundCard *recorder, SoundCard *player) = 0;
	////END 针对嵌入式Linux设备使用调参 END//////
#endif
	/**
	 * 针对嵌入式Linux设备使用调参
	 *
	 * 设置音频参数
	 * @param
	 */
	virtual void setAudioParams(int aec_level, int aec_delay, int agc_level, int ans_level, float ns_thres) = 0;
	/**
	 * 设置音频参数，影响的是别人听我的音质;默认samplerate是16000,bitrate是64000
	 * @param samplerate 16000,或者48000
	 * @param bitrate 32000,48000,64000,96000,128000,192000
	 */
	virtual void setAudioQuality(int samplerate, int bitrate) = 0;
	/**
	 * 设置频道事件观察者
	 * @param observer 观察者对象
	 */
	virtual void setObserver(ChannelObserver *observer) = 0;
	/**
	 * 设置用户id
	 * @param uid 用户id
	 */
	virtual void setUid(uint32_t uid) = 0;
	/**
	 * 设置服务器,正式用户可自己部署服务器
	 * @param serverIp 服务器IP或域名
	 * @param serverPort 服务器端口
	 * @param serverKey 服务器通讯密钥
	 */
	virtual void setServer(const char *serverHost, int serverPort, const char *serverKey) = 0;
	/**
	 * 设置原始音频数据监听器
	 * @param observer 数据监听器
	 * @param record true，监听采集
	 * @param playback true，监听播放
	 */
	virtual void setAudioDataObserver(AudioDataObserver *observer, bool record, bool playback=false) = 0;
	/**
	 * 进入频道，进入成功还是失败的结果在回调通知
	 * @param roomId 房间号
	 * @param role 用户角色，可以是主播或者听众
	 */
	virtual void join(uint32_t roomId, ChannelRole role) = 0;
	/**
	 * 创建本地播放的ChannelPlayer，播放效果是本地能听到，但远端通话方不会听到
	 * @param samplerate 播放器的采样率,支持8000, 16000, 32000, 44100, 48000
	 * @param channel 播放器的声道数,支持1和2
	 * @return ChannelPlayer指针，不用了需要delete释放资源
	 */
	virtual ChannelPlayer *createLocalPlayer(int samplerate, int channel) = 0;
	/**
	 * 创建远端播放的ChannelPlayer，播放效果是远端通话方能听到，但自己本地不会听到
	 * 如果需要自己和频道其他成员都听到，则同时创建一个LocalPlayer和RemotePlayer，同时写入相同数据即可
	 * @param samplerate 播放器的采样率,支持8000, 16000, 32000, 44100, 48000
	 * @param channel 播放器的声道数,支持1和2
	 * @return ChannelPlayer指针，不用了需要delete释放资源
	 */
	virtual ChannelPlayer *createRemotePlayer(int samplerate, int channel) = 0;
	/**
	 * 改变角色，改变的结果在回调通知
	 * @param role TALKER:主播，可说可听; AUDIENCE:听众，只能听不能说
	 */
	virtual void changeRole(ChannelRole role) = 0;
	/**
	 * mute房间成员
	 * @param uid 用户id
	 * @param mute true为静音；false为不静音
	 */
	virtual void mute(uint32_t uid, bool mute) = 0;
	/**
	 * 调节用户说话音量
	 * @param uid 用户id
	 * @param vol [0-400],默认为100，0为无声
	 */
	virtual void adjustUserVolume(uint32_t uid, int vol) = 0;
	/**
	 * 调节自己说话音量
	 * @param vol [0-400],默认为100，0为无声
	 */
	virtual void adjustMicVolume(int vol) = 0;
	/**
	 * 调节总的播放音量
	 * @param vol [0-400],默认为100，0为无声
	 */
	virtual void adjustPlayVolume(int vol) = 0;
	/**
	 * 频道内录音
	 * @param wavFile 保存的wav文件路径，如果文件路径不存在，会创建
	 */
	virtual void startRecord(const char *wavFile) = 0;
	/**
	 * 停止录音
	 */
	virtual void stopRecord() = 0;
	/**
	 * 离开房间
	 */
	virtual void leave() = 0;

	virtual ~ChannelEngine() {};
};

	class ChannelFactory {
	public:
		/**
	     * 设置授权信息,GetChannelInstance方法前调用，非必须设置
	     * @param licenseDir 授权文件存放目录
	     * @param userSerial 用户序列号,便于设备标示绑定
	     */
		QTT_PUBLIC static void SetLicense(const char *licenseDir, const char *userSerial);
		/**
		 * 设置appkey,GetChannelInstance方法前调用，必须设置
		 * @param appkey appkey字符串
		 */
		QTT_PUBLIC static void SetAppkey(const char *appkey);
	    /**
	     * 初始化获取ChannelEngine对象指针,单例
	     * @return ChannelEngine对象指针
	     */
		QTT_PUBLIC static ChannelEngine *GetChannelInstance();
		/**
		 * 如果GetChannelInstance返回NULL空指针，调用该接口获取出错信息
		 * @return 出错信息
		 */
		QTT_PUBLIC static const char *GetError();
	};
}

#endif //QTTAUDIO_QTTCHANNEL_H
